package main;

import java.io.IOException;
import java.util.ArrayList;

public class Method {
	private ArrayList<String> lines = new ArrayList<String>();
	private ArrayList<Variable> parameters = new ArrayList<Variable>();
	private ArrayList<Variable> variables = new ArrayList<Variable>();
	private String type, name;
	
	public Method (String type,  String name) {
		this.type=type;
		this.name=name;
	}
	
	public String getName () {
		return this.name;
	}
	
	public String getType () {
		return this.type;
	}
	
	public void addParameter (Variable var) throws compilationException {
		Sjavac.addUniqVar (var, parameters);
	}
	
	public void addLine (String line) throws IOException, compilationException {
		lines.add(line);
	}

	public void checkCorrectness () throws compilationException {
		for (int i=0; i<lines.size(); i++) {
			String line=lines.get(i);
			if (CheckType.isCommand(line)){
				if (i==lines.size()-1 && !line.startsWith(CheckType.RETURN))
					throw new compilationException(
					"Error 15: Must have a return statment at the end of a method");
				handleCommand(line);
				
			}
			else if (CheckType.isBlock(line)) {
				// Removes last "{"
				line=TextProcessor.removeLast(line);
				
				TextProcessor processedLine = new TextProcessor(line);
				String nextWord=processedLine.findNextWord();
				// if statement
				if (nextWord.equals(CheckType.IF) || nextWord.equals(CheckType.WHILE)) {
					if (processedLine.getSeparatedSign().equals("(")) {
						String nextByBracket=processedLine.findNextSeparatedBy("\\)");
						//if (!(VariableType.BOOLEAN.getRegex().equals(findType(nextByBracket)))) {
						//	throw new compilationException("Error 9: If value, invalid");
						//}
						if (processedLine.getLine()!=null)
							throw new compilationException("Error 9: UnKnown command");
					}
					else
						throw new compilationException("Error 9: UnKnown command");
				}
			}
			else
				throw new compilationException("Error 9: UnKnown command");
			
		}
	}
	
	private boolean isExistVariable (String name) {
		boolean isExist=false;
		for (Variable v: this.variables) {
			if (v.getName().equals(name))
				isExist=true;
		}
		return isExist;
	}
	
	private boolean isExistParameter (String name) {
		boolean isExist=false;
		for (Variable p: this.parameters) {
			if (p.getName().equals(name))
				isExist=true;
		}
		return isExist;
	}
	
	private boolean isValueMuchType (String value, String type) throws compilationException {
		if (!CheckType.isValueMuchType(value, type)) {
			for (Variable v: this.variables) {
				if (v.getName().equals(value))
					return v.getType().equals(type);
			}
			
			return CheckType.getmethodType(value).equals(type);
		}
		return true;
			
	}

	public void checkParamCorrectness(String params) throws compilationException {
		
		TextProcessor processedParameters = new TextProcessor(params);
		
		int i=0;
		/*while (processedParameters.indexOf(",")!=-1) {
			String nextByComma=processedParameters.findNextSeparatedBy(",");
			if (!findType(nextByComma).equals(this.parameters.get(i).getType()))
					throw new compilationException("Error 11: Not fit method parameter");
			i++;
		}
		String finalParam=processedParameters.getLine();
		if (!findType(finalParam).equals(this.parameters.get(i).getType()))
				throw new compilationException("Error 11: Not fit method parameter");*/
	}
	
	public void handleCommand (String line) throws compilationException {
		line=TextProcessor.removeLast(line);
		TextProcessor processedLine = new TextProcessor(line);
		String nextWord=processedLine.findNextWord();
		
		// return statement
		if (nextWord.equals(CheckType.RETURN)) {
			if (processedLine.getSeparatedSign().equals(" ")) {
				if (!isValueMuchType(processedLine.getLine(), this.type))
					throw new compilationException(
							"Error 9: Can't return other type than method's return statment");
			}
		}
		
		// variable statement
		else if (nextWord.equals(CheckType.FINAL) || CheckType.isVariableType(nextWord)) {
			Sjavac.addUniqVar (CorrectnessAndHandle.handleVariable(line,false), variables);
		}
		
		// Exist variable
		else if (isExistVariable(nextWord)) {
			if (processedLine.getSeparatedSign().equals("=")) {
				for (Variable v: this.variables){
					if (v.getName().equals(nextWord)) {
						String variableValue=processedLine.getLine();
						v.setValue(variableValue);
					}
				}
			}
			else
				throw new compilationException("Error 9: UnKnown command");
		}
		
		// Exist member
		else if (CorrectnessAndHandle.isExistMember(nextWord)) {
			if (processedLine.getSeparatedSign().equals("=")) {
				for (Variable m: Sjavac.members){
					if (m.getName().equals(nextWord))
						m.setValue(processedLine.getLine());
				}
			}
			else
				throw new compilationException("Error 9: UnKnown command");
		}
		
		// Exist parameter
		else if (isExistParameter(nextWord)) {
			if (processedLine.getSeparatedSign().equals("=")) {
				for (Variable m: this.parameters){
					if (m.getName().equals(nextWord)) {
						String variableValue=processedLine.getLine();
							Sjavac.addUniqVar (new Variable(m.getIsFinal(), m.getType(),
									m.getName(), variableValue), variables);
					}
				}
			}
			else
				throw new compilationException("Error 9: UnKnown command");
		}
		// Exist method
		else if (CorrectnessAndHandle.isExistMethod(nextWord)) {
			CheckType.getmethodType(line);
		} 
		else
			throw new compilationException("Error 9: UnKnown command");
	}
}
